/**
 * @Name image compressor 
 * @Desc 图片压缩工具类（使用 canvas）
 */
class ImageCompressor {
	constructor(){
		console.log("Image Compressor Gets Ready.");
	}
	
	/**
	 * 将文件对象转化为 base64 Data URL
	 * @param {二进制文件流} file 
	 * @param {回调函数，返回 base64 Data URL} callback 
	 **/
	readFileAsDataURL(file, callback){
		// 如果file未定义，返回null
		if(!file) return callback(null);

		// 创建读取文件对象
		let fileReader = new FileReader();		
		fileReader.readAsDataURL(file);	// 读取file文件,得到的结果为base64位
		fileReader.onload = function(){	
			let _this = this, imgBase64DataURL = _this.result;	// fileReader 读取到的 base64 Data URL
			callback && callback(imgBase64DataURL);
		}
	}
	
	/**
	 * 将 base64 Data URL 转换为文件对象
	 * @param {baseURL} dataUrl 
	 * @param {文件名称} filename 
	 * @return {文件二进制流}
	 */
	dataURLToFile(dataUrl, filename) {
		if(!dataUrl) return null;
		let arr = dataUrl.split(','), 
			mime = arr[0].match(/:(.*?);/)[1],
			base64Str = atob(arr[1]), 
			len = base64Str.length, 
			unit8Arr = new Uint8Array(len);
		while(len--){
			unit8Arr[len] = base64Str.charCodeAt(len);
		}
		return new File([unit8Arr], filename, {type: mime});
	}
	
	/**
	 * 使用 canvas 绘图并压缩
	 * @param {baseURL} dataUrl 文件 base64 dataUrl
	 * @param {optimizedOptions} 图片压缩的配置选项 {压缩图宽度width，文件类型 fileType，压缩质量 quality}
	 * @param {callback} 回调函数 
	 * @return {newImageData} 新文件的 dataUrl
	 */
	canvasDrawImage(dataUrl, optimizedOptions, callback){
		let image = new Image();
		image.src = dataUrl;
		image.onload = function(){
			// 获得图片的长宽比例
			let _self = this, scale = _self.width / _self.height;
			let optimizedWidth = optimizedOptions.width || 0, fileType = optimizedOptions.fileType || "image/jpeg", quality = optimizedOptions.quality || 0.92;
			// console.log(scale);
			
			//创建一个canvas，并获取其上下文					
			let canvas = document.createElement('canvas'), context = canvas.getContext('2d');
			
			//获取压缩后的图片宽度,如果width为0，默认原图宽度
			canvas.width = optimizedWidth == 0 ? _self.width : optimizedWidth;
			
			//获取压缩后的图片高度,如果width为0，默认原图高度
			canvas.height = optimizedWidth == 0 ? _self.height : parseInt(optimizedWidth / scale);
			
			//把图片绘制到canvas上面
			context.drawImage(image, 0, 0, canvas.width, canvas.height);
			
			//压缩图片，获取到新的base64Url
			let newImageData = canvas.toDataURL(fileType, quality);
			
			callback && callback(newImageData);
		}
	}
	 
	/**
	 * 压缩方法
	 * @param {参数obj} parms 
	 * @param {文件二进制流} parms.file ，必传
	 * @param {优化目标文件大小} parms.optimizedSize ，不传初始赋值 0
	 * @param {输出图片宽度} parms.width ，不传初始赋值 0，按比缩放无需传高度
	 * @param {输出图片名称} parms.fileName ，不传初始赋值 image
	 * @param {压缩图片程度} parms.quality ，值范围0~1，不传初始赋值 0.92。
	 * @param {回调函数} parms.done ，压缩后的回调函数，压缩成功将返回 file 对象，不成功则返回错误信息
	 **/
	compress(parms){
		//文件读取与图片加载等事件都是异步的，因此需要在回调函数中才能获取返回值
		if(parms && parms.done){
			//如果file没定义，返回null
			if(parms.file == undefined) return parms.done(null);

			let _this = this;

			//给参数赋初始值
			let optimizedSize = parms.hasOwnProperty("optimizedSize") ? parms.optimizedSize : 0,
				width = parms.hasOwnProperty("width") ? parms.width : 0,
				filename = parms.hasOwnProperty("filename") ? parms.filename: "image",
				quality = parms.hasOwnProperty("quality") ? parms.quality : 0.92,				
				fileType = parms.file.type;	// console.log(fileType) //image/jpeg
				
			// 判读文件类型是否为图片
			if(fileType.indexOf("image") == -1){
				console.log("请选择图片文件进行压缩理");
				return parms.done({code: -1, msg: "Only_Required_Image"});
			}

			// 读取 file 文件,得到的结果为 base64 字符串 Data URL
			_this.readFileAsDataURL(parms.file, function(base64DataURL){
				if(base64DataURL){
					//如果当前 fileSize 比优化目标小，直接输出
					let fileSize = parms.file.size;
					if(optimizedSize > fileSize){
						console.log("无需压缩");
						//直接返回原文件信息，parms.file 是一个 JS File 对象，dataURL 是图片的 base64 DataURL
						return parms.done({code: 0, msg: "Need_Not_Compress", data: {file: parms.file, dataURL: base64DataURL}});
					}
					
					//使用 canvas 绘图并压缩处理，参数：(bas64DataURL, 图片压缩配置参数 {压缩图宽度, 文件类型, 压缩质量}, 回到函数)					
					_this.canvasDrawImage(base64DataURL, {width, fileType, quality}, function(newImageData){
						//将 newImageData 转化成文件流
						let resultFile = _this.dataURLToFile(newImageData, filename);
						
						//判断如果 optimizedSize 有限制，且压缩后的图片大小比优化目标大，就报告错误
						if(optimizedSize > 0 && optimizedSize < resultFile.size){						
							console.log("未优化到目标压缩大小！上传图片尺寸太大，请重新选择合适图片上传");
							parms.done({code: -1, msg: "Image_Too_Large"});
						} else{
							//返回文件信息，resultFile 是一个 JS File 对象，dataURL 是压缩图的 base64 DataURL
							parms.done({code: 0, msg: "Complete", data: {file: resultFile, dataURL: newImageData}});
						}
					});
				}
			});
		}
	}
}

//es module 导出
export default ImageCompressor;

